from abc import ABC, abstractmethod
import time
import threading
from app.config import logger
from app.utils import HttpClient, LangDetectUtil
from app.api.schemas import TextTransResult, Lang

# 创建线程本地存储对象
thread_local = threading.local()


class AbstractTranslator(ABC):
    """
    抽象翻译器类
    """

    class ThreadLocalVars:
        """线程本地变量"""

        def __init__(
            self,
            content: str,
            src_lang: Lang,
            target_lang: Lang,
            use_proxy=False,
            max_text_limit=5000,
        ):
            self.content = content
            self.src_lang = src_lang
            self.target_lang = target_lang
            self.use_proxy = use_proxy
            self.max_text_limit = max_text_limit

    def __init__(self, url, content_type="application/json"):
        self.url = url
        self.http_client = HttpClient(self.url)
        self.content_type = content_type

    def _set_thread_local_vars(
        self, content: str, src_lang: Lang, target_lang: Lang, use_proxy=False
    ):
        """设置线程本地变量"""
        thread_local.vars = self.ThreadLocalVars(
            content, src_lang, target_lang, use_proxy
        )

    def _update_thread_local_var(self, var_name: str, value):
        """更新线程本地变量的值"""
        if not hasattr(thread_local, "vars") or thread_local.vars is None:
            raise ValueError("Thread local variables are not set")
        if not hasattr(thread_local.vars, var_name):
            raise AttributeError(f"Thread local variable '{var_name}' does not exist")
        setattr(thread_local.vars, var_name, value)

    def _get_thread_local_vars(self) -> ThreadLocalVars:
        """获取线程本地变量"""
        return thread_local.vars

    def _clear_thread_local_vars(self):
        """清除线程本地变量"""
        thread_local.vars = None

    @abstractmethod
    def _get_request_url(self):
        """获取请求url"""
        pass

    @abstractmethod
    def _get_headers(self):
        """获取请求头"""
        pass

    @abstractmethod
    def _get_body(self):
        """获取请求体"""
        pass

    @abstractmethod
    def _get_cookie(self):
        """获取cookie"""
        pass

    @abstractmethod
    def _parse_repsonse(self, response):
        """解析响应"""
        pass

    def _detect_language(self, content):
        """检测语言"""
        return LangDetectUtil.detect(content)

    def translate(
        self, content: str, src_lang: Lang, target_lang: Lang, use_proxy=False
    ):
        """
        翻译
        """
        result = TextTransResult(src=content, from_lang=src_lang, to_lang=target_lang)
        self.translate_entity(result, use_proxy)
        return result

    def translate_entity(self, trans_entity: TextTransResult, use_proxy=False):
        """
        翻译
        """
        content = trans_entity.src
        src_lang = trans_entity.from_lang
        target_lang = trans_entity.to_lang
        logger.info(
            f"开始翻译，源语言：{src_lang}，目标语言：{target_lang}，内容：{content[:30]}{'...' if len(content) > 30 else ''}"
        )
        self._set_thread_local_vars(content, src_lang, target_lang, use_proxy)
        start = time.time()
        try:
            # 如果内容为空，则直接返回
            if content.strip() == "":
                trans_entity.set_result(content)
                return

            # 如果源语言为自动检测，则调用检测语言方法
            if src_lang == Lang.AUTO:
                src_lang = self._detect_language(content)
                self._update_thread_local_var("src_lang", src_lang)
                trans_entity.from_lang = src_lang
                logger.info(f"自动检测源语言为：{src_lang}")

            data = self._get_body()
            is_json_content_type = self.content_type == "application/json"
            headers = self._get_headers()
            response = self.http_client.post(
                self._get_request_url(),
                use_proxy,
                headers=headers,
                json=(
                    data if is_json_content_type else None
                ),  # 如果是json格式，则使用json参数
                data=(
                    data if not is_json_content_type else None
                ),  # 如果不是json格式，则使用data参数
                verify=False,
                timeout=10,  # 设置请求超时时间
            )
            if not response or response.raise_for_status():
                raise Exception("请求接口失败，未返回数据！")

            # 解析翻译结果
            trans_entity.set_result(self._parse_repsonse(response))
        except Exception as e:
            logger.error(f"翻译失败，错误信息：{e}")
            trans_entity.set_result(None)
        finally:
            self._clear_thread_local_vars()
            logger.info(f"翻译结束，耗时：{time.time() - start:.2f}秒")
